import requests
import requests
import bs4
from bs4 import BeautifulSoup
import time
import json
import os
from urllib.parse import urlencode, urlparse, parse_qs, urljoin
import ssl
import logging
import platform

# 配置日志
logging.basicConfig(level=logging.INFO, format='%(asctime)s - %(levelname)s - %(message)s')

# 全局session配置
session = requests.Session()
# 禁用SSL验证（仅用于测试）
session.verify = False
# 取消SSL警告
requests.packages.urllib3.disable_warnings(requests.packages.urllib3.exceptions.InsecureRequestWarning)

# 配置SSL上下文
context = ssl.create_default_context()
context.check_hostname = False
context.verify_mode = ssl.CERT_NONE

# 设置连接和读取超时
session.timeout = 30

class CourtCaseSpider:
    def __init__(self):
        # 设置请求头，模拟浏览器访问
        self.headers = {
            'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Safari/537.36',
            'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8',
            'Accept-Language': 'ja-JP,ja;q=0.9,en-US;q=0.8,en;q=0.7',
            'Connection': 'keep-alive'
        }
        self.base_url = 'https://www.courts.go.jp'
        self.search_url = 'https://www.courts.go.jp/hanrei/search1/index.html'
        # 使用全局session
        self.session = session
        
    def search_cases(self, keyword, start_page=1, max_pages=10):
        """搜索指定关键词的案例"""
        results = []
        current_page = start_page
        
        # 构建搜索参数
        search_params = {
            'query1': keyword,
            'query2': '',
            'filter[judgeDateMode]': '2',
            'filter[judgeGengoFrom]': '令和',
            'filter[judgeYearFrom]': '1',
            'filter[judgeMonthFrom]': '1',
            'filter[judgeDayFrom]': '31',
            'filter[judgeGengoTo]': '令和',
            'filter[judgeYearTo]': '12',
            'filter[judgeMonthTo]': '12',
            'filter[judgeDayTo]': '31',
            'filter[jikenGengo]': '',
            'filter[jikenYear]': '',
            'filter[jikenCode]': '',
            'filter[jikenNumber]': '',
            'filter[courtType]': '',
            'filter[courtSection]': '',
            'filter[courtName]': '',
            'filter[branchName]': '',
        }
        
        # 使用urlencode构建URL，避免字符串拼接错误
        search_url = f"{self.search_url}?{urlencode(search_params)}#searched"
        print(f"开始搜索关键词：{keyword}")
        print(f"搜索URL：{search_url}")
        
        try:
            # 第一页
            page_results, next_page_url = self._parse_search_page(search_url)
            results.extend(page_results)
            
            # 继续翻页
            while next_page_url and current_page < max_pages:
                current_page += 1
                print(f"正在爬取第{current_page}页...")
                page_results, next_page_url = self._parse_search_page(next_page_url)
                results.extend(page_results)
                
                # 避免请求过快
                time.sleep(1.5)
                
        except Exception as e:
            print(f"搜索过程中发生错误：{str(e)}")
        
        print(f"搜索完成，共找到{len(results)}个案例")
        return results
        
    def _parse_search_page(self, url):
        """解析搜索结果页面"""
        results = []
        next_page_url = None
        
        try:
            # 发送请求
            try:
                print(f"正在请求URL: {url}")
                # 使用session发送请求
                response = self.session.get(url, headers=self.headers)
                response.encoding = 'utf-8'
                print(f"请求成功，状态码: {response.status_code}")
                print(f"响应内容长度: {len(response.text)} 字符")
                
                # 保存响应内容用于调试
                if len(results) == 0:
                    with open('debug_response.html', 'w', encoding='utf-8') as f:
                        f.write(response.text)
                    print("调试信息已保存到 debug_response.html")
                    
            except requests.exceptions.SSLError as e:
                print(f"SSL错误: {str(e)}")
                # 尝试使用urllib.request作为备选方案
                print("尝试使用urllib.request替代方法...")
                try:
                    import urllib.request
                    opener = urllib.request.build_opener(
                        urllib.request.HTTPSHandler(context=context)
                    )
                    urllib.request.install_opener(opener)
                    req = urllib.request.Request(url, headers=self.headers)
                    with urllib.request.urlopen(req, timeout=30) as response:
                        html = response.read().decode('utf-8')
                        print(f"urllib.request请求成功，响应长度: {len(html)} 字符")
                        # 保存调试信息
                        if len(results) == 0:
                            with open('debug_response.html', 'w', encoding='utf-8') as f:
                                f.write(html)
                            print("调试信息已保存到 debug_response.html")
                        # 创建模拟response对象
                        response = type('obj', (object,), {'text': html, 'status_code': 200})
                except Exception as urllib_err:
                    print(f"urllib.request也失败: {str(urllib_err)}")
                    raise
            except requests.exceptions.ConnectionError as e:
                print(f"连接错误: {str(e)}")
                # 可以尝试添加重试逻辑或其他备选方案
                raise
            except Exception as e:
                print(f"请求错误: {str(e)}")
                raise
            
            # 解析HTML
            soup = BeautifulSoup(response.text, 'html.parser')
            
            # 查找案例列表 - 根据实际HTML结构调整
            case_list = soup.find('table', class_='module-sub-page-fixed-table search-result-table')
            if case_list:
                cases = case_list.find_all('tr')
                print(f"在第1页找到 {len(cases)} 个案例")
                
                for case in cases:
                    # 提取案例信息
                    case_info = self._extract_case_info(case)
                    if case_info:
                        results.append(case_info)
            
            # 查找下一页链接
            next_page_element = soup.find('a', class_='next_page')
            if next_page_element and 'href' in next_page_element.attrs:
                next_page_url = self.base_url + next_page_element['href']
                
        except Exception as e:
            print(f"解析页面时发生错误：{str(e)}")
        
        return results, next_page_url
        
    def _extract_case_info(self, case_element):
        """提取单个案例信息"""
        try:
            print("开始提取案例信息...")
            
            # 获取所有单元格（可能包含th和td）
            cells = case_element.find_all(['th', 'td'])
            if len(cells) < 3:
                print(f"单元格数量不足: {len(cells)}")
                return None
            
            # 提取判决名称和链接 - 标题在第一个单元格（th）中
            title_cell = cells[0]
            title_element = title_cell.find('a')
            if not title_element:
                print("未找到标题元素")
                return None
            
            title = title_element.text.strip()
            print(f"找到标题: {title}")
            
            # 修复链接（使用urljoin来处理相对路径）
            link = urljoin(self.base_url, title_element['href']) if title_element.get('href') else ''
            print(f"链接: {link}")
            
            # 提取判决日期和其他详情 - 详情在第二个单元格（td）中
            detail_cell = cells[1]
            # 获取原始的p标签内容，用于详细拆分
            detail_paragraphs = detail_cell.find_all('p')
            all_paragraphs = [p.get_text(separator=' ', strip=True) for p in detail_paragraphs if p.get_text(strip=True)]
            
            # 获取完整的案例详情文本
            case_details = detail_cell.get_text(separator=' ', strip=True)
            print(f"案例详情: {case_details}")
            
            # 提取判决日期
            date_text = ''
            import re
            date_match = re.search(r'令和\d+年\d+月\d+日', case_details)
            if date_match:
                date_text = date_match.group()
                print(f"提取到日期: {date_text}")
            
            # 提取案件类型
            type_text = ''
            if '判決' in case_details:
                type_text = '判決'
            elif '控訴' in case_details:
                type_text = '控訴'
            elif '抗告' in case_details:
                type_text = '抗告'
            elif '破棄自判' in case_details:
                type_text = '破棄自判'
            print(f"案件类型: {type_text}")
            
            # 提取裁判所信息
            court_text = ''
            court_match = re.search(r'(最高裁判所|高等裁判所|地方裁判所|家庭裁判所|知的財産高等裁判所)', case_details)
            if court_match:
                court_text = court_match.group()
                print(f"裁判所: {court_text}")
            
            # 提取裁判书链接 - 在第三个单元格（td.file-col）中
            pdf_cell = cells[2]
            pdf_link_element = pdf_cell.find('a', href=lambda x: x and ('pdf' in x.lower() or '.pdf' in x.lower()))
            full_text_link = ''
            if pdf_link_element and 'href' in pdf_link_element.attrs:
                # 修复PDF链接（使用urljoin）
                full_text_link = urljoin(self.base_url, pdf_link_element['href'])
                print(f"PDF链接: {full_text_link}")
            
            # 提取更多详细信息
            case_number = ''  # 案件编号
            case_name = ''    # 案件名称
            original_court = ''  # 原审法院
            original_case_number = ''  # 原审案件编号
            legal_issues = []  # 法律问题
            
            # 从段落中提取详细信息
            if all_paragraphs:
                # 第一个段落通常包含案件编号和名称
                first_paragraph = all_paragraphs[0]
                # 尝试提取案件编号（如：令和6(ネ)10072）
                case_num_match = re.search(r'(令和\d+\([^)]+\)\d+)', first_paragraph)
                if case_num_match:
                    case_number = case_num_match.group(1)
                    # 提取案件名称（案件编号后面的部分）
                    case_name_part = first_paragraph.replace(case_number, '').strip()
                    if case_name_part:
                        case_name = case_name_part
                
                # 第二个段落可能包含日期、裁判所和原审信息
                if len(all_paragraphs) > 1:
                    second_paragraph = all_paragraphs[1]
                    # 尝试提取原审法院和编号
                    original_court_match = re.search(r'(東京地方裁判所|大阪地方裁判所|横浜地方裁判所|京都地方裁判所)\s+(令和\d+\([^)]+\)\d+)', second_paragraph)
                    if original_court_match:
                        original_court = original_court_match.group(1)
                        original_case_number = original_court_match.group(2)
                
                # 后续段落可能包含法律问题
                if len(all_paragraphs) > 2:
                    for para in all_paragraphs[2:]:
                        # 提取非空的法律问题
                        if para.strip():
                            legal_issues.append(para.strip())
            
            # 构建并返回详细的案例信息字典
            case_info = {
                'title': title,
                'link': link,
                'date': date_text,
                'type': type_text,
                'court': court_text,
                'full_text_link': full_text_link,
                # 新增的详细字段
                'case_number': case_number,
                'case_name': case_name,
                'original_court': original_court,
                'original_case_number': original_case_number,
                'legal_issues': legal_issues,
                'all_paragraphs': all_paragraphs,
                'raw_details': case_details
            }
            print(f"成功提取详细案例信息")
            return case_info
            
        except Exception as e:
            print(f"提取案例信息时发生错误：{str(e)}")
            import traceback
            print(traceback.format_exc())
            return None
            
    def save_results(self, results, keyword):
        """保存搜索结果到文件"""
        # 创建结果目录
        if not os.path.exists('results'):
            os.makedirs('results')
            
        # 保存为JSON文件
        filename = f"results/{keyword}_cases.json"
        
        with open(filename, 'w', encoding='utf-8') as f:
            json.dump(results, f, ensure_ascii=False, indent=2)
            
        print(f"结果已保存到：{filename}")
        return filename

def main_from_java(keyword=None, max_pages=1, output_file=None, return_json=False):
    """
    供Java程序调用的主函数接口
    
    参数:
    keyword (str): 搜索关键词
    max_pages (int): 最大爬取页数
    output_file (str): 输出文件名，为None时自动生成
    return_json (bool): 是否返回JSON字符串（用于命令行调用）
    
    返回:
    dict/list: 搜索结果
    """
    # 创建爬虫实例
    spider = CourtCaseSpider()
    
    if not keyword:
        keyword = "労働契約"  # 默认关键词
    
    # 搜索案例
    cases = spider.search_cases(keyword, max_pages=max_pages)
    
    # 保存结果
    if cases:
        # 如果指定了输出文件，则使用指定的文件名，否则自动生成
        if output_file:
            # 确保目录存在
            os.makedirs(os.path.dirname(os.path.abspath(output_file)), exist_ok=True)
            with open(output_file, 'w', encoding='utf-8') as f:
                json.dump(cases, f, ensure_ascii=False, indent=2)
            print(f"结果已保存到：{output_file}")
        else:
            # 使用默认的保存方法
            spider.save_results(cases, keyword)
        
        # 如果需要返回JSON字符串
        if return_json:
            return json.dumps(cases, ensure_ascii=False, indent=2)
        
        return cases
    else:
        print("未找到任何案例，可能是SSL连接问题或网页结构已更改。")
        print("请查看debug_response.html文件了解更多信息。")
        
        # 返回空列表或JSON空数组
        if return_json:
            return json.dumps([], ensure_ascii=False, indent=2)
        
        return []

# 命令行接口
if __name__ == "__main__":
    import sys
    import argparse
    
    # 创建命令行参数解析器
    parser = argparse.ArgumentParser(description='日本法院案例搜索爬虫 - 可被Java程序调用')
    parser.add_argument('--keyword', '-k', type=str, help='搜索关键词', default='労働契約')
    parser.add_argument('--max-pages', '-p', type=int, help='最大爬取页数', default=1)
    parser.add_argument('--output', '-o', type=str, help='输出JSON文件路径', default=None)
    parser.add_argument('--to-stdout', '-s', action='store_true', help='将结果输出到标准输出（JSON格式）')
    parser.add_argument('--show-info', action='store_true', help='显示系统信息')
    
    # 解析命令行参数
    args = parser.parse_args()
    
    # 如果需要显示系统信息
    if args.show_info:
        print("\n==== 系统信息 ====")
        print(f"Python版本: {platform.python_version()}")
        print(f"requests版本: {requests.__version__}")
        print(f"BeautifulSoup版本: {bs4.__version__}")
        print("==================\n")
    
    # 执行搜索并获取结果
    result = main_from_java(
        keyword=args.keyword,
        max_pages=args.max_pages,
        output_file=args.output,
        return_json=args.to_stdout
    )
    
    # 如果需要输出到标准输出
    if args.to_stdout:
        print(result)  # 输出JSON字符串到标准输出
    
    # 正常退出
    sys.exit(0)